﻿using System;
using System.Collections.Generic;
using SFML.Graphics;

namespace Discipulus
{
	/// <summary>
	/// The base class for all GUI-elements.
	/// </summary>
	
	abstract class Control
	{
		private Image skin;

		public Image Skin
		{
			get
			{
				return skin;
			}

			set
			{
				skin = value;

				OnSkinChanged();
			}
		}

		private Control parent;

		public Control Parent
		{
			get
			{
				return parent;
			}

			set
			{
				parent = value;

				// Only parents will be drawn automatically. Children are drawn by their parents.

				if (value == null)
					Game.Drawn += OnDraw;
				else
					Game.Drawn -= OnDraw;
			}
		}


		public List<Control> Children = new List<Control>();
		public IntRect Bounds;

		protected RenderImage texture;
		protected bool textureIsDirty = true;
		protected Sprite sprite = new Sprite();

		private static Vector2 position = new Vector2();
		private static readonly Color clearColor = new Color(255, 255, 255, 0);

		protected Control(IntRect bounds = new IntRect(), Control parent = null, string skin = "DefaultSkin.png")
		{
			Game.Updated += OnUpdate;

			// The skin is set directly so it won't invoke OnSkinChanged.

			this.skin = ResourceManager.GetImage(skin);

			Parent = parent;
			Bounds = bounds;

			// A texture is created for caching the control.

			texture = new RenderImage((uint)Bounds.Width, (uint)Bounds.Height);

			textureIsDirty = true;

			sprite.Image = texture.Image;
		}

		public void OnUpdate(object s, EventArgs e)
		{
			if (textureIsDirty)
			{
				texture.Clear(clearColor);

				DoDraw();

				foreach (var child in Children)
					child.OnDraw(this, null);

				texture.Display();

				textureIsDirty = false;
			}

			position.X = Bounds.Left;
			position.Y = Bounds.Top;

			sprite.Position = position;
		}

		public void OnDraw(object s, EventArgs e)
		{
			Game.Window.Draw(sprite);
		}

		public abstract void DoDraw();

		public virtual void OnSkinChanged() { }
	}
}
